package puzzle.hashikake.solver;

import java.util.ArrayList;
import java.util.List;

import tomoto.util.RectArray;

class CombinationDictionary {
	public static final CombinationDictionary INSTANCE = new CombinationDictionary();
	
	@SuppressWarnings("serial")
	private static class CombinationList extends ArrayList<Integer> {}
	
	private RectArray<CombinationList> m_combinations;

	private CombinationDictionary() {
		m_combinations = new RectArray<CombinationList>(5, 9, CombinationList.class);

		for (int slotPairs = 0; slotPairs <= 4; slotPairs++) {
			for (int remainings = 0; remainings <= slotPairs * 2; remainings++) {
				m_combinations.set(slotPairs, remainings, createCombination(slotPairs, remainings));
			}
		}

	}

	private CombinationList createCombination(int slotPairs, int remainings) {
		assert slotPairs >= 0 && slotPairs <= 4;
		assert remainings >= 0 && remainings <= slotPairs * 2;

		if (slotPairs == 0) {
			CombinationList result = new CombinationList();
			result.add(0);
			return result;
		}

		CombinationList result = new CombinationList();
		for (int i = 0; i <= 2; i++) {
			int outerCombination = 1 << i;
			CombinationList innerCombinations = getCombinationsAux(slotPairs - 1, remainings - i);
			if (innerCombinations != null) {
				for (int innerCombination : innerCombinations) {
					result.add((innerCombination << 4) | outerCombination);
				}
			}
		}
		return result;
	}

	public List<Integer> getCombinations(int slotPairs, int remainings) {
		return getCombinationsAux(slotPairs, remainings);
	}

	private CombinationList getCombinationsAux(int slotPairs, int remainings) {
		if (remainings >= 0 && remainings <= slotPairs * 2) {
			return m_combinations.get(slotPairs, remainings);
		} else {
			return null;
		}
	}
}
